﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.IO;
using PServiceBus.Core.Runtime;
using System.Net.Http;
using System.Collections.Specialized;
using PServiceBus.WebAPI.Controllers;
using PServiceBus.Services.Web;
using PServiceBus.Core.Manager;

namespace PServiceBus.WebAPI.Transports {
    internal abstract class BaseHttpTransport {

        internal StreamWriter Writer { get; set; }

        internal dynamic Handler { get; set; }

        internal string Subscriber { get; set; }

        internal string TransportName { get; set; }

        internal string ClientToken { get; set; }

        internal abstract string ContentType { get; }

        internal bool IsDurable { get; set; }

        internal HttpRequestMessage Request { get; set; }

        internal TransportConnectionInfo ConnectionInfo { get; set; }

        internal Dictionary<string, string> Headers { get; set; }

        internal virtual void Init() { }

        internal void Send(string json) {
            if (!IsConnected) return;
            var ex = MethodHelper.Try(() => {
                Write(json);
            });
            if (ex != null) 
                IsConnected = false;
        }

        private bool _isConnected;
        internal bool IsConnected {
            get {
                var isConnected = _isConnected;
                var ex = MethodHelper.Try(() => isConnected = Writer.BaseStream != null && (Writer.BaseStream.CanWrite || Writer.BaseStream.CanRead));
                return IsConnected = isConnected && ex == null;
            }
            set {
                _isConnected = value;
                if (!_isConnected) {
                    MethodHelper.Try(() => {
                        if (Handler != null) Handler.Stop();
                        //Cleanup Subscriber if subscriber loose connection and is not durable
                        //Optimization to prevent dead subscribers lingering forever due to lost connections
                        if (!IsDurable)
                            WebMessageBus.Select(ConnectionInfo.ConnectionID, ConnectionInfo.UserName,
                                ConnectionInfo.Password, Headers)
                                .DeleteSubscriber(Subscriber);
                        ESBController.EndStreaming(Subscriber, TransportName);
                    });
                }
            }
        }

        internal void Close() {
            MethodHelper.Try(() =>
            {
                if (Handler != null) Handler.Stop();
                Writer.Close();
            });
            WebStreamManagementManager.Execute(webMgmt => webMgmt.Close(ClientToken, Headers));
        }

        protected NameValueCollection QueryString {
            get {
                return HttpUtility.ParseQueryString(Request.RequestUri.Query);
            }
        }

        protected abstract void Write(string json);
    }
}
